<?php
/**
 * I-Cafe framework
 * 
 * @category CF
 * @package CF_Db
 * @link http://www.i-cafe.org
 * @license http://www.i-cafe.org/license
 * @version 04-04-2010
 * @author tcl_java@yahoo.com
 */

/**
 * A class provider for many common operations on table.
 * <code>
 * 	class Products extends CF_Db_Table_Abstract
 * 	{
 * 		$this->_name = 'products';
 * 		$this->_id = 'id';
 * 	}
 * 
 * 	$products = new Products();
 * 	$products->insert(array("name" => "Product 1", "price" => 300));
 * 	$products->get(1);
 * </code>
 */
abstract class CF_Db_Table_Abstract extends CF_Component
{
	/**
	 * @var string
	 */
	protected $_name = null;
	
	/**
	 * @var string
	 */
	protected $_id = 'id';
	
	/**
	 * @return void
	 */
	public function __construct()
	{
	}
	
	/**
	 * @return string
	 */
	public function getTableName()
	{
		if(null === $this->_name){
			$this->setTableName(strtolower(get_class($this)));
		}
		
		return $this->_name;
	}
	
	/**
	 * 
	 * @param string $name
	 * @return CF_Db_Table_Abstract $this
	 */
	public function setTableName($name)
	{
		$this->_name = CF_Db::getInstance()->tablePrefix . $name;
		return $this;
	}
	
	/**
	 * 
	 * @param array $data
	 * @param boolean $returnInsertId [optional]
	 * @return int
	 */
	public function insert($data, $returnInsertId = true)
	{
		require_once 'CF/Db/Insert.php';
		$insert = new CF_Db_Insert();
		$insert->table($this->getTableName())->data($data);
		
		return $insert->execute($returnInsertId);
	}
	
	/**
	 * 
	 * @param array $data
	 * @param string|CF_Db_Expr $where [optional]
	 * @return int
	 */
	public function update($data, $where = null)
	{
		require_once 'CF/Db/Update.php';
		$update = new CF_Db_Update();
		$update->table($this->getTableName())->data($data)->where($where);
		
		return $update->execute();
	}
	
	/**
	 * 
	 * @param int|array $ids
	 * @param array $data
	 * @return int
	 */
	public function updateById($ids, $data)
	{
		if(!is_array($ids)) $ids = array($ids);
		require_once 'CF/Db/Expr.php';
		$where = new CF_Db_Expr($this->_id . ' IN(%s)', $ids);
		return $this->update($data, $where);
	}
	
	/**
	 * 
	 * @param string|CF_Db_Expr $where [optional]
	 * @return int
	 */
	public function delete($where = null)
	{
		$delete = new CF_Db_Delete();
		$delete->table($this->getTableName())->where($where);
		
		return $delete->execute();
	}
	
	/**
	 * 
	 * @param int|array $id
	 * @return int
	 */
	public function deleteById($ids)
	{
		if(!is_array($ids)) $ids = array($ids);
		$where = new CF_Db_Expr($this->_id . ' IN(%s)', $ids);
		return $this->delete($where);
	}
	
	/**
	 * 
	 * @param string|array $columns [optional]
	 * @param string|CF_Db_Expr $where [optional]
	 * @param string|CF_Db_Expr $order [optional]
	 * @param int $limitCount [optional]
	 * @param int $limitOffset [optional]
	 * @return CF_Db_Store
	 */
	public function select($columns = '*', $where = null, $order = null, $limitCount = null, $limitOffset = null)
	{
		$select = new CF_Db_Select();
		$select->table($this->getTableName(), $columns, $where)
			->order($order)
			->limit($limitCount, $limitOffset);

		return $select->execute();
	}
	
	/**
	 * 
	 * @param string|array $ids
	 * @param string|array $columns [optional]
	 * @param string|CF_Db_Expr $where [optional]
	 * @param string|CF_Db_Expr $order [optional]
	 * @param int $limitCount [optional]
	 * @param int $limitOffset [optional]
	 * @return CF_Db_Store
	 */
	public function find($ids, $columns = '*', $where = null, $order = null)
	{
		if(!is_array($ids)) $ids = array($ids);
		$ids = CF_Db::getInstance()->quote($ids);
		$ids = implode(',', $ids);
		$w = "$this->_id IN ($ids)";
		if($where) $w .= ' ' . $where;
		
		return $this->select($columns, $w, $order);
	}
	
	/**
	 * 
	 * @param string $id
	 * @return boolean
	 */
	public function has($id)
	{
		return (boolean) $this->find($id)->getCount();
	}
	
	/**
	 * 
	 * @param mixed $ids
	 * @param string|array|CF_Db_Expr $columns [optional]
	 * @return array
	 */
	public function getAt($index, $ids, $columns = '*', $where = null)
	{
		$find = $this->find($ids, $columns, $where);
		return $find->getAt($index);
	}
	
	/**
	 * 
	 * @param int $id
	 * @param string|array|CF_Db_Expr $columns [optional]
	 * @param int|string $col
	 * @param int $row
	 * @return string
	 */
	public function getCell($id, $columns = '*', $col = 0, $row = 0)
	{
		$row = $this->getAt($row, $id, $columns);
		if(empty($row)) return null;
		
		if(is_string($col)) return $row[$col];
		
		if(0 === $col) return current($row);
		if($col >= count($row)) return array_pop($row);
		
		$i = 0;
		foreach ($row as $col => $value) {
			if($i == $col) return $value;
		}
	}
	
	/**
	 * 
	 * @param string $column
	 * @param string|CF_Db_Expr $where [optional]
	 * @param string|array $order [optional]
	 * @param int $limit [optional]
	 * @param int offset [optional]
	 */
	public function getCol($column, $where = null, $order = null, $limit = null, $offset = null)
	{
		return $this->select($column, $where, $order, $limit, $offset)
					->getColumn($column);
	}
	
	/**
	 * 
	 * @return array 
	 */
	public function getMeta()
	{
		$select = new CF_Db_Select();
		$select->table($this->getTableName(), '*')->limit(1);
		$store = $select->execute();
		
		return $store->getMeta();
	}
}
